package cal

import (
	"strconv"
	"teggame/input"
	"teggame/output"
)

func Start(ipt *input.Input, opt *output.Output) {
	me := ipt.Robots[0]
	// 发现离我最近的病毒
	step, dir := DescoveryVirusDir(ipt)
	// 获取病毒信息
	x, y := GetDestinationPosition(me.X, me.Y, step, dir)
	virus := ipt.GetVirusInfo(x, y)
	// 判断是否可以发动攻击
	skillID := CheckVirusCanbeAttach(ipt, virus, step)

	if me.Dir != dir {
		// 转向
		TurnDir(opt, me.Dir, dir)
	} else if skillID == 0 {
		opt.WithMsg(1, strconv.Itoa(x)+","+strconv.Itoa(y))
		// 发起移动指令
		if me.FootStatus == 0 {
			opt.Switch()
		} else {
			// 闪现
			if step > SkillList[4].Range && me.FlashFreezeTime == 0 {
				opt.Flash(GetAttachPosition(me.X, me.Y, x, y, 4))
			} else if step > 0 {
				opt.Go()
			} else {
				opt.Stop()
			}
		}
	} else {
		// 通知队友准备攻击目标
		opt.WithMsg(2, strconv.Itoa(virus.Id))
		// 切换为足式
		if me.FootStatus == 1 {
			opt.Switch()
		} else {
			// 发起攻击指令
			if skillID == 7 {
				opt.Bomb(GetAttachPosition(me.X, me.Y, x, y, skillID))
			} else if skillID == 6 {
				opt.Throw(GetAttachPosition(me.X, me.Y, x, y, skillID))
			} else if skillID == 3 {
				opt.Attack(virus.Id)
			} else {
				opt.Stop()
			}
		}

	}
}

func GetAttachPosition(meX, meY, destX, destY, skillID int) (int, int) {
	if meX == destX {
		meY += SkillList[skillID].Range
	} else {
		meX += SkillList[skillID].Range
	}
	return meX, meY
}

func TurnDir(opt *output.Output, meDir int, turnDir int) {
	switch meDir {
	case 0: // 正X
		switch turnDir {
		case 0: // 正X
		case 1: // 正Y
			opt.TurnRight()
		case 2: // 负X
			opt.TurnBack()
		case 3: // 负Y
			opt.TurnLeft()
		}
	case 1: // 正Y
		switch turnDir {
		case 0: // 正X
			opt.TurnLeft()
		case 1: // 正Y
		case 2: // 负X
			opt.TurnRight()
		case 3: // 负Y
			opt.TurnBack()
		}
	case 2: // 负X
		switch turnDir {
		case 0: // 正X
			opt.TurnBack()
		case 1: // 正Y
			opt.TurnLeft()
		case 2: // 负X
		case 3: // 负Y
			opt.TurnRight()
		}
	case 3: // 负Y
		switch turnDir {
		case 0: // 正X
			opt.TurnRight()
		case 1: // 正Y
			opt.TurnBack()
		case 2: // 负X
			opt.TurnLeft()
		case 3: // 负Y
		}
	}
}

// 判断病毒是否可以被攻击
func CheckVirusCanbeAttach(ipt *input.Input, virus input.Virus, step int) int {
	// 目标方向没有病毒，不进行攻击
	if virus.RewardScore == 0 {
		return 0
	}
	// 根据距离刷选出可用的攻击技能
	if step <= 6 && ipt.Robots[0].ThrowFreezeTime == 0 {
		// 此时只有酒精技能可以攻击到病毒
		// 判断有没有导弹技能在该病毒位置, 有的话就优先使用酒精技能, 前提是病毒的血量在组合伤害之上，否则就是浪费
		if (GetTeammateReleasedSkill(7, ipt) && (virus.Hp > SkillList[7].Damage+SkillList[6].Damage)) ||
			(virus.Hp > SkillList[6].Damage*5 && virus.Hp < SkillList[6].Damage*8) {
			// 此时可以单独释放酒精技能
			return 6
		}
	}

	if step <= 4 && ipt.Robots[0].BombFreezeTime == 0 {
		// 此处需要考虑导弹有3帧的等待时间
		if (GetTeammateReleasedSkill(6, ipt) && (virus.Hp > SkillList[7].Damage+SkillList[6].Damage*3)) ||
			(virus.Hp > SkillList[7].Damage && virus.Hp < SkillList[6].Damage*8) {
			return 7
		}
	}

	// 普攻
	if step <= 2 {
		return 3
	}

	return 0

}

func GetTeammateReleasedSkill(skillID int, ipt *input.Input) bool {
	for _, skill := range ipt.Skills {
		if skill.Id == skillID && IsTeammate(ipt, skill.RobotId) {
			return true
		}
	}
	return false
}

func IsTeammate(ipt *input.Input, robotID int) bool {
	me := ipt.Robots[0]
	for _, robot := range ipt.Robots {
		if robot.Id == robotID && robot.Id != me.Id && me.Side == robot.Side {
			return true
		}
	}
	return false
}

// 根据冷却时间筛选出可用的技能
func FilterAvailabelSkill() {

}

// 根据距离筛选出可用的攻击技能
func FilterAvailabelAttachSkill() {

}

// 获取病毒的坐标
func GetDestinationPosition(x, y, step, dir int) (int, int) {
	if dir == 0 {
		x += step
	} else if dir == 1 {
		y += step
	} else if dir == 2 {
		x -= step
	} else {
		y -= step
	}
	return x, y
}

// 首先寻找离自己最近的病毒
func DescoveryVirusDir(ipt *input.Input) (int, int) {
	var step, dir int
	var hasVirus bool
	for i := 0; i < 4; i++ {
		_step, _hasVirus := RoadCal(ipt, i, 1)
		if _hasVirus {
			if hasVirus && step < _step {
				continue
			}
			step = _step
			hasVirus = _hasVirus
			dir = i
		} else {
			if hasVirus {
				continue
			} else if _step > step {
				step = _step
				hasVirus = _hasVirus
				dir = i
			}
		}
	}
	return step, dir
}

// 寻找病毒路径计算
func RoadCal(ipt *input.Input, dir int, stepNums int) (int, bool) {
	maps := ipt.Map
	me := ipt.Robots[0]
	switch dir {
	case 0:
		if me.X+stepNums < 22 {
			str := string(maps[me.Y][me.X+stepNums])
			if str != "#" && str != "v" {
				stepNums++
				return RoadCal(ipt, dir, stepNums)
			} else if str == "v" {
				return stepNums, true
			} else {
				return stepNums, false
			}
		} else {
			stepNums--
			return stepNums, false
		}
	case 1:
		if me.Y+stepNums < 16 {
			str := string(maps[me.Y+stepNums][me.X])
			if str != "#" && str != "v" {
				stepNums++
				return RoadCal(ipt, dir, stepNums)
			} else if str == "v" {
				return stepNums, true
			} else {
				return stepNums, false
			}
		} else {
			stepNums--
			return stepNums, false
		}
	case 2:
		if me.X-stepNums > 0 {
			str := string(maps[me.Y][me.X-stepNums])
			if str != "#" && str != "v" {
				stepNums++
				return RoadCal(ipt, dir, stepNums)
			} else if str == "v" {
				return stepNums, true
			} else {
				return stepNums, false
			}
		} else {
			stepNums--
			return stepNums, false
		}
	default:
		if me.Y-stepNums > 0 {
			str := string(maps[me.Y-stepNums][me.X])
			if str != "#" && str != "v" {
				stepNums++
				return RoadCal(ipt, dir, stepNums)
			} else if str == "v" {
				return stepNums, true
			} else {
				return stepNums, false
			}
		} else {
			stepNums--
			return stepNums, false
		}
	}

}
